from . import news_blue
from flask import render_template, session, abort, g, jsonify, request
from technews.models import User, News, Comment
import logging
from technews import constants, db, response_code
from technews.utils.comment import user_login_data


@news_blue.route("/news_comment", methods=["POST"])
@user_login_data
def news_comment():
    """
    新闻评论
    1.判断用户是否登录
    2.接受参数：news_id, comment, parent_id
    3.校验参数：判断参数是否齐全，判断news_id 和parent_id是否是整数
    4.判断要评论的新闻是否存在，只有存在才能评论
    5.根据参数，创建Comment模型类的对象，并给属性赋值
    6.同步数据到数据库
    7.响应评论的结果，记得将评论数据返回给前端，方便前端展示评论后的内容
    :return:
    """
    # 1.判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno==response_code.RET.SESSIONERR, errmsg="用户未登录")

    # 2.接受参数：news_id, comment, parent_id
    json_dict = request.json
    news_id = json_dict.get("news_id")
    comment_content = json_dict.get("comment")
    parent_id = json_dict.get("parent_id")

    # 3.校验参数：判断参数是否齐全，判断news_id 和parent_id是否是整数
    if not all([news_id, comment_content]):   # 如果是直接评论的新闻，可以不传
        return jsonify(errno=response_code.RET.PARAMERR, errmsg="缺少必传参数")
    try:
        news_id = int(news_id)
        if parent_id:
            parent_id = int(parent_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.PARAMERR, errmsg="参数错误")

    # 4.判断要评论的新闻是否存在，只有存在才能评论
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg="查询新闻数据失败")
    if not news:
        return jsonify(errno=response_code.RET.NODATA, errmsg="新闻不存在")

    # 5.根据参数，创建Comment模型类的对象，并给属性赋值
    comment = Comment()
    comment.user_id = user.id
    comment.news_id = news_id
    comment.content = comment_content
    if parent_id:
        comment.parent_id = parent_id

    # 6.同步数据到数据库
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=response_code.RET.DBERR, errmsg="存储评论数据失败")

    # 7.响应评论的结果，记得将评论数据返回给前端，方便前端展示评论后的内容
    return jsonify(errno=response_code.RET.OK, errmsg="OK", data=comment.to_dict())


@news_blue.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    """
    新闻收藏
    只有登录用户才能收藏新闻
    1.判断用户是否登录
    2.接受参数：news_id,,action
    3.校验参数，判断参数是否齐全，判断action是否在指定的范围
    4.判断新闻数据是否存在，只有存在的新闻才能收藏
    5.根据action的值，实现收藏或者取消收藏
    6.将数据同步到数据库
    7.返回收藏或者取消收藏的结果
    :return:
    """
    # 1.判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=response_code.RET.SESSIONERR, errmsg="用户未登录")

    # 2.接受参数：news_id,,action
    json_dict = request.json
    news_id = json_dict.get('news_id')
    action = json_dict.get('action')

    # 3.校验参数，判断参数是否齐全，判断action是否在指定的范围
    if not all([news_id, action]):
        return jsonify(errno=response_code.RET.PARAMERR, errmsg="缺少参数")
    if action not in ["collect", "cancel_collect"]:
        return jsonify(errno=response_code.RET.PARAMERR, errmsg="参数错误")

    # 4.判断新闻数据是否存在，只有存在的新闻才能收藏
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg="查询新闻数据失败")
    if not news:
        return jsonify(errno=response_code.RET.NODATA, errmsg="新闻不存在")

    # 5.根据action的值，实现收藏或者取消收藏
    if action == "collect":
        # 收藏
        if news not in user.collection_news:
            # 如果当前的新闻没有被收藏，就把当前的新闻添加到当前登录用户的收藏列表中
            user.collection_news.append(news)
    else:
        # 取消收藏
        if news in user.collection_news:
            user.collection_news.remove(news)

    # 6.将数据同步到数据库
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=response_code.RET.DBERR, errmsg="操作失败")

    # 7.返回收藏或者取消收藏的结果
    return jsonify(errno=response_code.RET.OK, errmasg="操作成功")


@news_blue.route("/detail/<int:news_id>")
@user_login_data
def news_detail(news_id):
    """
    新闻详情
    :param news_id: 新闻id
    :return: 新闻详情
    1. 查询用户基本信息
    2. 查询点击排行
    3.查询新闻详情信息
    """
    # # 1. 查询用户基本信息
    # user_id = session.get("user_id", None)
    # user = None
    # if user_id:
    #     try:
    #         user = User.query.get(user_id)
    #     except Exception as e:
    #         logging.error(e)

    # # 上面代码封装到了get_user_info
    # from technews.utils.comment import get_user_info
    # user = get_user_info()

    # 从装饰器上文中读取g.user，这里是下文
    user = g.user

    # 2. 查询点击排行
    news_clicks = None
    try:
        news_clicks = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    except Exception as e:
        logging.error(e)

    # 3.查询新闻详情信息
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
    if not news:
        # 找不到新闻详情，有一个404界面，将来捕获404，然后对所有的404进行统一的处理
        abort(404)

    # 更新新闻点击量
    news.clicks += 1
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()

    # 4.需要判断当前登录用户是否收藏过该新闻
    is_collected = False
    if user:
        if news in user.collection_news:
            is_collected = True

    # 构造渲染详情页上下文
    context = {
        "user": user.to_dict() if user else None,
        "news_clicks": news_clicks,
        "news": news.to_dict(),
        "is_collected": is_collected
    }

    return render_template("news/detail.html", context=context)